/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package uk.ac.cranfield.mzqviewer;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.table.AbstractTableModel;
import uk.ac.liv.jmzqml.model.mzqml.Assay;
import uk.ac.liv.jmzqml.model.mzqml.Column;
import uk.ac.liv.jmzqml.model.mzqml.GlobalQuantLayer;
import uk.ac.liv.jmzqml.model.mzqml.QuantLayer;
import uk.ac.liv.jmzqml.model.mzqml.Row;

/**
 *
 * @author Jun Fan@cranfield
 */
public class DataTable extends AbstractTableModel {

    ArrayList<String> header = new ArrayList<String>();
//    ArrayList<? extends MzQuantMLObject> objs = new ArrayList<MzQuantMLObject>();
//    ArrayList<ArrayList<Double>> values = new ArrayList<ArrayList<Double>>();
    ArrayList<ArrayList<String>> values = new ArrayList<ArrayList<String>>();
    String title;

    public DataTable(String quantObj, QuantLayer ql) {
        title = ql.getDataType().getCvParam().getName() + " in " + quantObj;
        List<Row> rows = ql.getDataMatrix().getRow();
        if (rows.isEmpty()) {
            header.add("Object");
        } else {
            String clazzName = rows.get(0).getObjectRef().getClass().toString();
            int index = clazzName.lastIndexOf(".");
            header.add(clazzName.substring(index + 1));
        }
        for (Object obj : ql.getColumnIndex()) {
            if (obj instanceof Assay) {
                header.add(((Assay) obj).getId());
            } else {
                header.add(obj.toString());
            }
        }
        for (Row row : rows) {
            ArrayList<String> one = new ArrayList<String>();
            Method m;
            try {
                m = row.getObjectRef().getClass().getDeclaredMethod("getId", new Class[0]);
                one.add(m.invoke(row.getObjectRef(), new Object[0]).toString());
            } catch (Exception ex) {
                Logger.getLogger(DataTable.class.getName()).log(Level.SEVERE, null, ex);
            }
            one.addAll(row.getValue());
            values.add(one);
        }
    }

    public DataTable(String quantObj, GlobalQuantLayer gql) {
        title = gql.getId() + " in " + quantObj;
        header.add("Object");
        for (Column col : gql.getColumnDefinition().getColumn()) {
            header.add(col.toString());
        }
        for (Row row : gql.getDataMatrix().getRow()) {
            ArrayList<String> one = new ArrayList<String>();
            one.add(row.getObjectRef().toString());
            one.addAll(row.getValue());
            values.add(one);
        }
    }

    public void saveAsCSV(String filename, boolean append) {
        StringBuilder sb = new StringBuilder();
        sb.append(title);
        sb.append("\n");
        for (String str : header) {
            sb.append(str);
            sb.append(",");
        }
        sb.deleteCharAt(sb.length() - 1);
        sb.append("\n");
        for (ArrayList<String> one : values) {
            for (String str : one) {
                sb.append(str);
                sb.append(",");
            }
            sb.deleteCharAt(sb.length() - 1);
            sb.append("\n");
        }
//        System.out.print(sb.toString());
        try {
            File file = new File(filename);
            boolean existing = false;
            if(file.length()>0) existing = true;
            BufferedWriter out = new BufferedWriter(new FileWriter(file,append));
            if(append && existing) out.write("\n");
            out.write(sb.toString());
            out.close();
            if(!append || !existing) System.out.println("Result file "+file.getCanonicalPath()+" has been generated");
        } catch (Exception ex) {
        }
    }

    @Override
    public int getRowCount() {
//        return objs.size();
        return values.size();
    }

    @Override
    public int getColumnCount() {
        return header.size();
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        if (rowIndex < 0 || rowIndex >= values.size()) {
            return null;
        }
//        if(columnIndex == 0){
//            return objs.get(rowIndex);
//        }else{
        return values.get(rowIndex).get(columnIndex);
//        }
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }
}
